import {pinyin} from "pinyin-pro";

interface Item {
  [key: string]: unknown;
}

interface Segment {
  letter: string;
  data: Item[];
}

/**
 * 根据指定标签的拼音将项目数组分段并排序
 *
 * 此函数旨在处理中文字符的字符串，将其转换为拼音，然后根据拼音的首字母对数组进行分段。
 *
 * 它支持在每个分段内进行排序，并且可以选择性地包括没有匹配项的字母分段。
 *
 * 适用于[uni-indexed-list](https://uniapp.dcloud.net.cn/component/uniui/uni-indexed-list.html)组件数据结构
 *
 *
 * @param {Item[]} arr - 要分段和排序的项目数组。每个项目是一个对象，其属性值预期为中文字符的字符串。
 * @param {boolean} [empty=false] - 如果为真，则结果将包括所有字母的分段，即使没有匹配的项目也是如此。如果为假，则只包括有项目的分段。
 * @param {string} [label='label'] - 用于分段和排序的项目对象中的键。默认为 'label'。
 * @returns {Segment[] | null} 一个Segment对象数组，每个对象代表一个字母的分段，包含匹配该分段的排序项目。
 *                             如果输入数组无效或环境不支持localeCompare，则返回null。
 *
 * @example
 * // 示例用法：
 * const items = [
 *   { label: '苹果' }, // 苹果
 *   { label: '香蕉' }, // 香蕉
 *   { label: '橙子' }, // 橙子
 *   { label: '榴莲' }, // 榴莲
 *   { label: '葡萄' }, // 葡萄
 * ];
 * const sortedSegments = segmentAndSortByPinyin(items, false);
 * console.log(sortedSegments);
 * // 输出可能如下：
 * // [
 * //   { letter: 'c', data: [{ label: '橙子' }] },
 * //   { letter: 'l', data: [{ label: '榴莲' }] },
 * //   { letter: 'p', data: [{ label: '苹果' }, { label: '葡萄' }] },
 * //   { letter: 'x', data: [{ label: '香蕉' }] }
 * // ]
 */
export function segmentAndSortByPinyin(arr: Item[], empty: boolean = false, label: string = "label"): Segment[] | null {
  // 检查环境是否支持localeCompare和Array.isArray方法
  if (!String.prototype.localeCompare || !Array.isArray(arr)) {
    return null; // 如果不支持，则函数返回null
  }

  // 创建一个包含所有英文字母和'#'的数组，每个字母代表一个分段
  const letters = "abcdefghjklmnopqrstwxyz#".split("");
  // 将每个字母映射为一个分段对象，每个对象包含字母和一个空的数据数组
  const segs: Segment[] = letters.map(letter => ({ letter, data: [] }));

  // 查找或创建默认分段（'#'），用于不匹配任何字母的项
  const defaultSegment = segs.find(segment => segment.letter === '#');
  if (!defaultSegment) {
    throw new Error("默认分段（'#'）未找到。"); // 如果没有找到默认分段，则抛出错误
  }

  // 遍历输入数组的每个项
  arr.forEach((item) => {
    const itemString = item[label]; // 获取项的标签值
    // 使用pinyin库将标签值转换为拼音，并获取首字母
    if (typeof itemString === 'string') {
      const firstLetter = getFirstLetterOfPinyin(itemString);
      // 根据首字母找到对应的分段，如果没有找到，则使用默认分段
      let targetSegment = segs.find(segment => segment.letter === firstLetter) || segs.find(segment => segment.letter === '#');
      if (!targetSegment) {
        targetSegment = defaultSegment;
      }

      // 将项添加到找到的分段的数据数组中
      targetSegment.data.push(item);
    }
  });

  // 对每个分段的数据数组进行排序
  segs.forEach(segment => segment.data.sort((a, b) => (a[label] as string).localeCompare(b[label] as string)));

  // 根empty参数决定是否返回包含空数据数组的分段
  return empty ? segs : segs.filter(segment => segment.data.length);
};

/**
 * 获取输入字符串的拼音首字母。
 * @param inputString
 */
function getFirstLetterOfPinyin(inputString: string): string {
  const pinyinResult = pinyin(inputString, { pattern: 'first', toneType: 'none', type: 'array' });
  const firstLetter = pinyinResult[0]?.charAt(0).toLowerCase();
  return firstLetter || '#';
}
export default segmentAndSortByPinyin;
